package com.guanyu.u2cache.manage;

import com.guanyu.u2cache.constant.ExcuConfig;
import com.guanyu.u2cache.model.CacheConsistence;
import lombok.SneakyThrows;
import org.springframework.scheduling.annotation.Async;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author zhouyunjian
 * @date 2023/12/06 11:20
 * 缓存一致性管理:
 * 1、获取到缓存异常信息
 * 2、对异常缓存进行即时处理
 * 3、处理失败则放于队列中，记录情况
 **/

public class ConsistenceManage {

    private ArrayBlockingQueue<CacheConsistence> queue = new ArrayBlockingQueue(1000);

    // todo 多次处理缓存无效的情况，则进行存储处理，需要考虑分布式使用场景
    // private ArrayBlockingQueue<CacheConsistence> falQueue = new ArrayBlockingQueue(100);

    private AtomicBoolean queueIsUse = new AtomicBoolean(false);

    private static final int MAX_FAIL_COUNT = 3;
    private static final ConsistenceManage singleton = new ConsistenceManage();

    public static ConsistenceManage getSingleton() {
        return singleton;
    }

    /**
     * 1、将失败缓存信息放入队列当中
     * 2、唤醒队列处理机制
     */
    @SneakyThrows
    @Async(ExcuConfig.name)
    public void pushCacheFail(CacheConsistence consistence) {
        this.queue.add(consistence);
        Thread.sleep(3000);
        this.notifyQueue();
    }

    /**
     * 队列处理，如果连续三次,则放入失败队列中
     */
    private void notifyQueue() {
        while (!queue.isEmpty() && !this.queueIsUse.get()) {
            this.queueIsUse.set(true);
            CacheConsistence poll = queue.poll();
            poll.addFailCount();
            try {
                poll.invoke();
                Thread.sleep(100);
            } catch (Exception e) {
                if (MAX_FAIL_COUNT > poll.getFailCount()) {
                    queue.offer(poll);
                }
//                else{
//                    falQueue.offer(poll);
//                }
            }
        }
    }
}
